#!/usr/bin/env python
#coding:utf-8
"""
Author:	rikugun
Site: http://rikugun.javaeye.com/

拷贝文件,发布到正式环境TEST_CRM

"""
import optparse
import os
import re
import shutil
from aix import TexudoBackend
from ConfigParser import RawConfigParser
from tydic_utils.base import get_conf_path
import pysvn
import subprocess

def sort_dirs(dir1,dir2):
	"""排序目录,优先编译 share 目录,再编译目录名短的
	@param dir1: 目录1
	@param dir2: 目录2
	@return int:  -1,1,0
	"""
	SHARE_DIR_NAME = 'share'
	if dir1.endswith(SHARE_DIR_NAME) and not dir2.endswith(SHARE_DIR_NAME):
		return -1
	elif dir2.endswith(SHARE_DIR_NAME) and not dir1.endswith(SHARE_DIR_NAME):
		return 1
	elif dir1.endswith(SHARE_DIR_NAME) and  dir2.endswith(SHARE_DIR_NAME):
		return dir1.find(SHARE_DIR_NAME) - dir2.find(SHARE_DIR_NAME)
	else:
		return len(dir1)-len(dir2)
def getIgnoreFiles(src,dst):
	if os.path.isfile(src):
		return set()
	os.chdir(src)
	return glob.glob('.*')

class MergerTools(object):
	"""合并工具类"""
	def __init__(self):
		super(MergerTools, self).__init__()
		self.env = RawConfigParser()
		self.env.read(get_conf_path())
		self.parser_args()
	def parser_args(self):
		"""
		获取参数
		"""
		opt = optparse.OptionParser("cmd [-m comments]  [-L listfile] filepath [other files]")
		opt.add_option("-m","--comments",help=u"提交的注释",default="commit to compile")
		opt.add_option("-L","--listfile",help=u"提交的文件列表")
		opt.add_option("-M","--mergetool",help=u"使用工具合并而非拷贝")
		opt.add_option("-q","--quite",action="store_true",help=u"安静模式,所有提示都选择Y")
		opt.add_option("-D","--delete",action="store_true",help=u"删除模式")
		opt.add_option("-d","--debug",action="store_true",help=u"调试模式")
		opts,files = opt.parse_args()
		if len(files) == 0 and opts.listfile is None:
			print u'请输入要提交文件,或者文件列表'
			print opt.print_usage()
			print __doc__
			exit(2)
		if not files and opts.listfile:
			files = [line for line in open(opts.listfile,'r').readlines() if not line.startswith('#')]
		#过滤文件名 如 CRM_TRANS/src/share/EssErrorTrans.txt
		file_like = re.compile(os.path.join(self.env.get('CRM','CRM'),'(.+)$'))
		self.files_set = set([file_like.match(os.path.realpath(os.path.join(os.getcwd(),it))).group(1).strip() for it in files])
		self.opts = opts
	def getInput(self,msg):
		"""获取用户输入,默认是NO
		@param msg:提示消息内容
		"""
		return self.opts.quite or raw_input(msg) not in ['n','no']
	def sysexec(cmd):
		"""执行命令幷返回结果
		@param cmd:执行的命令
		@return:
		"""
		msg = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE).communicate()
		#[0].decode('utf-8')
		if msg[1] is not None:
			print u'=============== 错误信息====================='
			print msg[1].decode('utf-8')
		if self.opts.debug:
			print u'================执行命令==================='
			print cmd
			print u'================我是分割线==================='
			print msg[0].decode('utf-8')
			print u'================命令完成==================='
		return msg
	def svn_add_list(self,files):
		for it in files:
			if self.sc.status(it)[0].text_status == pysvn.wc_status_kind.unversioned:
				self.sc.add(it)	
	def sync_files(self,src,dst):
		"""同步文件,并提交SVN
		需要在CRM目录下执行
		"""
		#源文件路径
		src_file_list =[]
		#目标文件路径
		dst_file_list = []
		#需要新增的文件
		add_dst_file_list = []
		self.sc = svn.Client()
		#TEST目录特殊处理
		if  dst.endswith('TEST') :
			dst = os.path.join(dst,'TEST_')
		else:
			dst = dst+os.sep
		
		#设置合并工具
		merge_cmd = self.opts.mergetool or self.env.get('MERGE_TOOL')
		
		file_list = '\n'.join(self.files_set)
		
		
		# 同步文件
		if	self.getInput('commit such files [\n%s\n] to [%s]? (y)es/no :' % (file_list,dst) ):
			for	x in  self.files_set:
				src_file_list.append(src+os.sep+x)
				sc.update(src_file_list[-1])
				dst_file_list.append(dst+x)
				self.sc.update(dst_file_list[-1])
				# print dst_path
				#过滤新加的文件,需要额外执行svn add命令
				if not os.path.exists(dst_file_list[-1]):
					if os.path.isdir(dst_file_list[-1]):
						os.makedirs(dst_file_list[-1])
						shutil.copytree(src_file_list[-1],dst_file_list[-1],ignore=getIgnoreFiles)
					else:
						os.makedirs(os.path.dirname(dst_file_list[-1]))
						shutil.copy2(src_file_list[-1],dst_file_list[-1])	
					# add_dst_file_list.append(dst_file_list[-1])
				else:
					sysexec(' '.join([merge_cmd,src_file_list[-1],dst_file_list[-1]]))
			self.svn_add_list(src_file_list)
			self.svn_add_list(dst_file_list)		
			print u'正在提交源目录文件[\n%s\n]' % '\n'.join(src_file_list)
			self.sc.checkin(src_file_list,self.opts.comments)
			print u'正在提交目标目录文件[\n%s\n]' % '\n'.join(dst_file_list)
			self.sc.checkin(dst_file_list,self.opts.comments)
		print u'脚本执行成功'
	
	def mergeFile(self,src,dst):
		"""合并文件"""
		if not os.path.exists(src):
			if os.path.isdir(src):
				os.makedirs(dst)
				shutil.copytree(src,dst,ignore=getIgnoreFiles)
			else:
				os.makedirs(os.path.dirname(dst))
				shutil.copy2(src,dst)
			self.sc.add(src)
			self.sc.add(dst)
		else:
			self.sc.update(src)
			self.sc.update(dst)
			msg = subprocess.Popen(' '.join([merge_cmd,src,dst]),shell=True,stdout=subprocess.PIPE).communicate()
			if msg[1] is not None:
				print u'=============== 错误信息====================='
				print msg[1].decode('utf-8')
				print u'=============== 错误信息====================='

			
	def merge_to_deploy(self):
		"""合并到部署目录"""
		self.sync_files(self.env.get('CRM','CRM'),self.env.get('CRM','TEST_CRM'))
	
	def merge_to_dev(self):
		"""合并到开发目录"""
		self.sync_files(self.env.get('CRM','CRM'),self.env.get('CRM','LOCAL_CRM'))
		#过滤需要编译的目录
		dir_list = list(set([ os.path.dirname(x) for x in self.files_set if x.endswith(tuple(
								self.env.get('CRM','SOURCE_FILE_EXT').split(',')))]))
		#排序文件目录
		dir_list.sort(sort_dirs)
		
		# 切换到服务器编译
		if self.getInput('Compile such files [\n%s\n] on Develop Server ? (y)es/no :' % ('\n'.join(self.files_set),)) :
			tn = TexudoBackend()
			try:
				if	tn.login() :
					print u'登录成功'
					#在服务器上更新文件
					tn.exe_cmd('svn up %s' % ' '.join(self.files_set))
					#逐个目录编译
					for dir_path in dir_list:
						tn.exe_cmd('cd ~/%s && make && make install ' % dir_path.replace('\\','/'))
			except Exception:
				print u"传输到服务器中编译发生错误"
				tn.close()
				exit(2)
		print u'脚本执行成功'

def m2t():
	MergerTools().merge_to_deploy()
	
def m2d():
	MergerTools().merge_to_dev()